//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ModelsReports.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
namespace ModelsReport {
  
  bool EqualScheme (TNode <String>* scheme, void* ref) {
    
    String* schemeRef = (String*)ref;

    return (!strcmp(scheme->Info()->Out(), schemeRef->Out()))?true:false;

  }
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ModelsReports::ModelsReports () {

  this->listFilenameIn                  = new TListE <String> ();
  this->folderReportsOut                = new String ();
  this->modelsSumaries                  = new TListE <ModelsSummaryByLigand> ();
  this->toString                        = new String ();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ModelsReports::ModelsReports (const ModelsReports& modelsReports) {

  this->listFilenameIn                  = new TListE <String> (modelsReports.listFilenameIn);
  this->folderReportsOut                = new String (modelsReports.folderReportsOut);
  this->modelsSumaries                  = new TListE <ModelsSummaryByLigand> (modelsReports.modelsSumaries);
  this->toString                        = new String (modelsReports.toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ModelsReports::ModelsReports (const ModelsReports* modelsReports) {

  this->listFilenameIn                  = new TListE <String> (modelsReports->listFilenameIn);
  this->folderReportsOut                = new String (modelsReports->folderReportsOut);
  this->modelsSumaries                  = new TListE <ModelsSummaryByLigand> (modelsReports->modelsSumaries);
  this->toString                        = new String (modelsReports->toString);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ModelsReports::~ModelsReports () {

  if (this->listFilenameIn)   delete this->listFilenameIn;
  if (this->folderReportsOut) delete this->folderReportsOut;
  if (this->modelsSumaries)   delete this->modelsSumaries;
  if (this->toString)         delete this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ModelsReports::ListFilenameIn (TListE <String>* listFilenameIn) {

  if (listFilenameIn)
    *(this->listFilenameIn) = *listFilenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ModelsReports::FolderReportsOut (String* folderReportsOut) {

  if (folderReportsOut)
    *(this->folderReportsOut) = *folderReportsOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ModelsReports::ModelsSumaries (TListE <ModelsSummaryByLigand>* modelsSumaries) {

  if (modelsSumaries)
    *(this->modelsSumaries) = *modelsSumaries;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* ModelsReports::ListFilenameIn (void) {

  return this->listFilenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ModelsReports::FolderReportsOut (void) {

  return this->folderReportsOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <ModelsSummaryByLigand>* ModelsReports::ModelsSumaries (void) {

  return this->modelsSumaries;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ModelsReports::LoadXMLFiles (void) {
  
  if (!this->listFilenameIn || !this->listFilenameIn->Length())
    return false;
  
  this->listFilenameIn->SetInitial();
  while (this->listFilenameIn->SetNext()) {
    
    ModelsSummaryByLigand* newModelsSummaryByLigand = new ModelsSummaryByLigand ();
    
    newModelsSummaryByLigand->FilenameIn(this->listFilenameIn->GetCurrent());
    
    if (newModelsSummaryByLigand->LoadXMLFile())
      this->modelsSumaries->Add(newModelsSummaryByLigand);
    else
      delete newModelsSummaryByLigand;
    
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ModelsReports::CSVReportsByLigand (String* headerModel) {

  if (!this->modelsSumaries   || !this->modelsSumaries->Length()    || 
      !this->folderReportsOut || !this->folderReportsOut->Length()  ||
      !headerModel || !headerModel->Length())
    return false;
  
  ofstream file;
  char     buffer [MAX_SIZE];
  
  this->modelsSumaries->SetInitial();
  while (this->modelsSumaries->SetNext()) {
    
    if (!this->modelsSumaries->GetCurrent()->Models())
      if (this->modelsSumaries->GetCurrent()->LoadXMLFile())
        return false;
    
    if (!this->modelsSumaries->GetCurrent()->Models())
      return false;
    
    sprintf(buffer, ((this->folderReportsOut->Out()[this->folderReportsOut->Length() - 1] == '/')?
                     ("%s%s.%s.report.table.csv\0"):
                     ("%s/%s.%s.report.table.csv\0")), this->folderReportsOut->Out(), 
                                                       this->modelsSumaries->GetCurrent()->LigandName()->Out(), 
                                                       headerModel->Out());    
    file.open(buffer, fstream::out);
    
    if (!file.is_open())
      return false;
    
    file << ModelsSummaryByLigand::ToCVSTableHeader().Out();
    file << this->modelsSumaries->GetCurrent()->ToCVSTable(headerModel)->Out();
    
    file.close();
    
  }
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ModelsReports::CSVReportsByModelType (String* headerModel) {

  if (!this->modelsSumaries   || !this->modelsSumaries->Length()    || 
      !this->folderReportsOut || !this->folderReportsOut->Length()  ||
      !headerModel || !headerModel->Length())
    return false;
  
  ofstream          file;
  char              buffer [MAX_SIZE];
  TListE <String>*  listScheme = new TListE <String> ();
  
  this->modelsSumaries->SetInitial();
  while (this->modelsSumaries->SetNext()) {
    
    ModelsSummaryByLigand* currentModelsSummaryByLigand = this->modelsSumaries->GetCurrent();
    
    if (!currentModelsSummaryByLigand->Models())
      if (currentModelsSummaryByLigand->LoadXMLFile())
        return false;
    
    if (!currentModelsSummaryByLigand->Models())
      return false;
    
    currentModelsSummaryByLigand->Models()->SetInitial();
    while (currentModelsSummaryByLigand->Models()->SetNext()) {
      
      ModelTotalResults* currentModelTotalResults = currentModelsSummaryByLigand->Models()->GetCurrent();
      String*            searchScheme             = listScheme->FirstOcurrence(ModelsReport::EqualScheme, currentModelTotalResults->Scheme());
      
      if (!searchScheme)
        listScheme->Add(new String (currentModelTotalResults->Scheme()));
      
    }

  }

  listScheme->SetInitial();
  while (listScheme->SetNext()) {
    
    sprintf(buffer, ((this->folderReportsOut->Out()[this->folderReportsOut->Length() - 1] == '/')?
                     ("%s%s.%s.report.table.csv\0"):
                     ("%s/%s.%s.report.table.csv\0")), this->folderReportsOut->Out(), 
                                                       headerModel->Out(),
                                                       listScheme->GetCurrent()->Out());    
    
    file.open(buffer, fstream::out);
    
    if (!file.is_open()) continue;
    
    file << ModelsSummaryByLigand::ToCVSTableHeader().Out();
    this->modelsSumaries->SetInitial();
    while (this->modelsSumaries->SetNext())
      file << this->modelsSumaries->GetCurrent()->ToLatexTableContent(listScheme->GetCurrent(), headerModel)->Out();
    
    file.close();
    
  }
  
  if (listScheme) delete listScheme;
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ModelsReports::LatexReportsByLigand (String* headerModel) {

  if (!this->modelsSumaries   || !this->modelsSumaries->Length()    || 
      !this->folderReportsOut || !this->folderReportsOut->Length()  ||
      !headerModel || !headerModel->Length())
    return false;
  
  ofstream file;
  char     buffer [MAX_SIZE];
  
  this->modelsSumaries->SetInitial();
  while (this->modelsSumaries->SetNext()) {
    
    if (!this->modelsSumaries->GetCurrent()->Models())
      if (this->modelsSumaries->GetCurrent()->LoadXMLFile())
        return false;
    
    if (!this->modelsSumaries->GetCurrent()->Models())
      return false;
    
    sprintf(buffer, ((this->folderReportsOut->Out()[this->folderReportsOut->Length() - 1] == '/')?
                     ("%s%s.%s.report.table.tex\0"):
                     ("%s/%s.%s.report.table.tex\0")), this->folderReportsOut->Out(), 
                                                       this->modelsSumaries->GetCurrent()->LigandName()->Out(), 
                                                       headerModel->Out());    
    file.open(buffer, fstream::out);
    
    if (!file.is_open())
      return false;
    
    file << ModelsSummaryByLigand::ToLatexBeginDoc().Out();
    file << ModelsSummaryByLigand::ToLatexBeginTable().Out();
    file << ModelsSummaryByLigand::ToLatexTableHeader().Out();
    
    file << this->modelsSumaries->GetCurrent()->ToLatexTableContent(headerModel)->Out();
    
    file << ModelsSummaryByLigand::ToLatexEndTable().Out();
    file << ModelsSummaryByLigand::ToLatexEndDoc().Out();
    
    file.close();
    
  }
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ModelsReports::LatexReportsByModelType (String* headerModel) {

  if (!this->modelsSumaries   || !this->modelsSumaries->Length()    || 
      !this->folderReportsOut || !this->folderReportsOut->Length()  ||
      !headerModel || !headerModel->Length())
    return false;
  
  ofstream          file;
  char              buffer [MAX_SIZE];
  TListE <String>*  listScheme = new TListE <String> ();
  
  this->modelsSumaries->SetInitial();
  while (this->modelsSumaries->SetNext()) {
    
    ModelsSummaryByLigand* currentModelsSummaryByLigand = this->modelsSumaries->GetCurrent();
    
    if (!currentModelsSummaryByLigand->Models())
      if (currentModelsSummaryByLigand->LoadXMLFile())
        return false;
    
    if (!currentModelsSummaryByLigand->Models())
      return false;
    
    currentModelsSummaryByLigand->Models()->SetInitial();
    while (currentModelsSummaryByLigand->Models()->SetNext()) {
      
      ModelTotalResults* currentModelTotalResults = currentModelsSummaryByLigand->Models()->GetCurrent();
      String*            searchScheme             = listScheme->FirstOcurrence(ModelsReport::EqualScheme, currentModelTotalResults->Scheme());
      
      if (!searchScheme)
        listScheme->Add(new String (currentModelTotalResults->Scheme()));
      
    }

  }

  listScheme->SetInitial();
  while (listScheme->SetNext()) {
    
    sprintf(buffer, ((this->folderReportsOut->Out()[this->folderReportsOut->Length() - 1] == '/')?
                     ("%s%s.%s.report.table.tex\0"):
                     ("%s/%s.%s.report.table.tex\0")), this->folderReportsOut->Out(), 
                                                       headerModel->Out(),
                                                       listScheme->GetCurrent()->Out());    
    
    file.open(buffer, fstream::out);
    
    if (!file.is_open()) continue;
    
    file << ModelsSummaryByLigand::ToLatexBeginDoc().Out();
    file << ModelsSummaryByLigand::ToLatexBeginTable().Out();
    file << ModelsSummaryByLigand::ToLatexTableHeader().Out();
    
    this->modelsSumaries->SetInitial();
    while (this->modelsSumaries->SetNext())
      file << this->modelsSumaries->GetCurrent()->ToLatexTableContent(listScheme->GetCurrent(), headerModel)->Out();
    
    file << ModelsSummaryByLigand::ToLatexEndTable().Out();
    file << ModelsSummaryByLigand::ToLatexEndDoc().Out();
    
    file.close();
    
  }
  
  if (listScheme) delete listScheme;
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ModelsReports ModelsReports::operator= (const ModelsReports& modelsReports) {

  *(this->folderReportsOut) = *(modelsReports.folderReportsOut);
  *(this->modelsSumaries)   = *(modelsReports.modelsSumaries);
  *(this->listFilenameIn)   = *(modelsReports.listFilenameIn);
  *(this->toString)         = *(modelsReports.toString);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
